import {
  BotGetGuildMessagePattern,
  BotGetMemberMessagePattern,
  BotGetUserMessagePattern,
  CacheGuildDto,
  CacheUserDto,
  GetCacheUserDto,
  GetGuildDto,
} from '@boticord/bot-client'
import { Controller } from '@nestjs/common'
import { Payload } from '@nestjs/microservices'
import { DiscordooService } from '@boticord/discordoo'
import { GetCacheMemberDto } from '@boticord/bot-client/dto/get-cache-member.dto'
import { CacheMemberDto } from '@boticord/bot-client/dto/cache-member.dto'

@Controller()
export class RpcController {
  constructor(
    private readonly discordoo: DiscordooService,
  ) {}

  /** get user from bot cache or fetch from discord */
  @BotGetUserMessagePattern()
  async getUser(@Payload() dto: GetCacheUserDto): Promise<CacheUserDto | null> {
    let user = await this.discordoo.client.users.cache.get(dto.userID)

    if (!user) {
      user = await this.discordoo.client.users.fetch(dto.userID)
    }

    if (!user) {
      return null
    }
  
    return {
      avatar: user.avatar ?? undefined,
      discriminator: user.discriminator,
      username: user.username,
      bot: user.bot,
    }
  }

  @BotGetMemberMessagePattern()
  async getMember(@Payload() dto: GetCacheMemberDto): Promise<CacheMemberDto | null> {
    let member = await this.discordoo.client.members.cache.get(dto.userID, { storage: dto.guildID })

    if (!member) {
      member = await this.discordoo.client.members.fetchOne(dto.guildID, dto.userID)
    }

    if (!member) {
      return null
    }

    return {
      joinedTimestamp: member.joinedTimestamp,
      roles: member.rolesList,
      nickname: member.nick,
    }
  }

  /** get guild from bot cache, if exists */
  @BotGetGuildMessagePattern()
  async getGuild(@Payload() dto: GetGuildDto): Promise<CacheGuildDto | null> {
    const guild = await this.discordoo.client.guilds.cache.get(dto.guildID)

    if (!guild) {
      return null
    }

    return {
      avatar: guild.icon ?? undefined,
      id: guild.id,
      members: guild.membersCount,
      name: guild.name,
      ownerID: guild.ownerId,
    }
  }
}
